<template>

  <!--弹窗 :close-on-click-modal="false" 点击遮罩层不关闭窗口 -->
  <div class="article-edit-container">
    <!-- status-icon 当表单校验不通过时, 输入框右侧有个 x 小图标 -->
    <el-form
      :rules="rules"
      ref="formData"
      :model="formData"
      label-width="100px"
      label-position="right"
    >
      <el-form-item label="标题:" prop="title">
        <el-input v-model="formData.title" placeholder="请输入标题"
                  maxlength="50" show-word-limit/>
      </el-form-item>
      <el-form-item label="标签:" prop="labelIds">
        <!--:show-all-levels="false" 仅显示最后一级， :filterable="true" 可搜索
        props{ multiple: true 多选， emitPath: false 只返回子节点的value } -->
        <el-cascader
          :disabled="disabled"
          style="display: block"
          v-model="formData.labelIds"
          :options="labelOptions"
          :show-all-levels="false"
          :props="{
              multiple: true,
              emitPath: false,
              children: 'labelList',
              value:'id',
              label: 'name'
            }"
          :filterable="true"
          clearable/>
      </el-form-item>

      <!-- 主图模块-->
      <el-form-item label="主图:" prop="imageUrl">
        <!--
          accept="image/png, image/jpeg" ：接收上传的类型
          action 指定上传地址，但是我们不用它默认的，所以给它空的，不能把它删除，默认这个必须要有
          show-file-list 是否显示已上传文件列表，因为只传一张，所以不要显示
          http-request 自定义上传实现
         -->
        <el-upload class="avatar-uploader"
                   accept="image/*"
                   action=""
                   :show-file-list="false"
                   :http-request="uploadMainImg">
          <img
            v-if="formData.imageUrl"
            :src="formData.imageUrl"
            class="avatar"
            alt=""/>
          <i v-else class="el-icon-plus avatar-uploader-icon"></i>
        </el-upload>
      </el-form-item>

      <!--是否公开-->
      <el-form-item label="是否公开:" prop="ispublic">
        <el-radio-group v-model="formData.ispublic">
          <el-radio :label="0">不公开</el-radio>
          <el-radio :label="1">公开</el-radio>
        </el-radio-group>
      </el-form-item>

      <!--简介-->
      <el-form-item label="简介:" prop="summary">
        <el-input v-model="formData.summary" type="textarea"
                  placeholder="请输入简介" :autosize="{ minRows: 3 }" maxlength="2000" show-wordlimit/>
      </el-form-item>

      <!-- 主体内容 -->
      <el-form-item label="内容:" prop="content">
        <!-- 主体内容，使用 mavon-editor 渲染出markdown编辑器
        autofocus 是否自动获取焦点
        -->
        <mavon-editor
          :autofocus="false"
          ref="md"
          v-model="formData.mdContent"
          @change="getMdHtml"
          @imgAdd="uploadContentImg"
          @imgDel="delContentImg"
        />
      </el-form-item>
    </el-form>
    <el-row type="flex" justify="center">
      <el-button
        type="primary"
        @click="submitForm('formData')">提交审核
      </el-button>
    </el-row>
  </div>

</template>

<script>
export default {
  middleware: 'auth', // 引用权限中间件

  // 校验
  validate({query}) {
    // 如果有传递id则是修改，
    if (query.id) {
      // 必须是number类型
      return /^\d+$/.test(query.id)
    }
    return true
  },

  // 服务端渲染
  async asyncData({query, app}) {
    // 查询分类与标签
    const {data} = await app.$getCategoryAndLabel()

    // 查询文章详情
    if (query.id) {
      const {data: formData} = await app.$getArticleById(query.id)
      return {
        labelOptions: data,
        formData: formData
      }
    }

    return {
      labelOptions: data
    }
  },

  data() {
    const validateLabel = (rule, value, callback) => {
      // value获取输入框的值
      // 有 value 值才校验，不然提交的时候会报错
      if (value && value.length > 5) {
        this.disabled = true // 禁止点击
        callback(new Error('最多可选5个标签'))
      } else {
        this.disabled = false // 可以选择
        callback() // 校验通过，直接放行
      }
    }

    const validateContent = (rule, value, callback) => {
      if (this.formData.mdContent && this.formData.htmlContent) {
        // 有内容则放行
        callback()
      } else {
        callback(new Error('请求输入文章内容'))
      }
    } // 不要有逗号

    return {
      rules: { // +++++
        // 标题
        title: [{required: true, message: '请输入标题', trigger: 'blur'}],

        // 标签id
        labelIds: [
          {required: true, message: '请选择标签', trigger: 'blur'},
          {validator: validateLabel, trigger: 'change'},
        ],

        // 是否公开
        ispublic: [
          {required: true, message: '请选择是否公开', trigger: 'change'}
        ],

        // 摘要
        summary: [
          {
            required: true,
            message: '请输入简介',
            trigger: 'blur'
          }
        ],

        // 文章内容
        content: [
          {
            validator: validateContent, trigger: 'change'
          }
        ]
      },
      // 表单数据
      formData: {
        imageUrl: null, // 写出来，不然图片显示不出来
        userId: this.$store.state.userInfo.uid,
        userImage: this.$store.state.userInfo.imageUrl,
        nickName: this.$store.state.userInfo.nickName
      },
      disabled: false, // 标签输入框默认可输入
      // labelOptions: [] // 标签下拉框
    }
  },
  methods: {
    // 提交表单
    submitForm(formName) {
      // 校验通过
      this.$refs[formName].validate((valid) => {
        if (valid) {
          console.log("校验通过，提交数据")
          console.log(this.formData)
          // 校验通过，提交数据
          this.submitData()
        } else {
          // 验证不通过
          return false;
        }
      })
    },

    // 2. 异步方法提交数据
    async submitData() {
      let response = null

      //  有id值则修改，没有id则新增
      if (this.formData.id) {
        response = await this.$updateArticle(this.formData)
      } else {
        response = await this.$addArticle(this.formData)
      }

      if (response.code === 20000) {
        // 提交成功,
        this.$message.success('提交成功，即将跳转到文章详情页')

        // 跳转到详情页, data封装的就是保存后的文章id
        this.$router.push(`/article/${response.data}`)
      }
    },


    // 上传主图
    uploadMainImg(file) {
      // 封装表单对象
      const data = new FormData()
      data.append('file', file.file)
      // 发送请求上传
      this.$uploadImg(data).then(response => {
        // 以防图片多次上传，上传成功后，把原来的图片删除
        this.deleteImg()

        // 删除后赋新值
        this.formData.imageUrl = response.data
      }).catch(() => {
        this.$message.error('上传失败')
      })
    },

    // 删除主图, 上传成功和关闭窗口调用删除上一次上传的图片
    deleteImg() {
      if (this.formData.imageUrl) {
        // 删除
        this.$deleteImg(this.formData.imageUrl)
      }
    },

    // mdContent: md 内容，htmlContent：转成后的html
    getMdHtml(mdContent, htmlContent) {
      //console.log('mdContent', mdContent)
      //console.log('htmlContent', htmlContent)
      this.formData.mdContent = mdContent
      this.formData.htmlContent = htmlContent
    },


    // 上传内容图片 (图片位置编号, File对象)
    uploadContentImg(pos, file) {
      // console.log('上传内容图片', file)

      // 第一步.将图片上传到服务器
      let fd = new FormData();
      fd.append('file', file);
      this.$uploadImg(fd).then(response => {
        if (response.code === 20000) {
          console.log(response)
          // 第二步.将返回的url替换到文本原位置! [...](0) -> ![...](url)
          this.$refs.md.$img2Url(pos, response.data)
        }
      })
    },

    // 删除内容图片
    delContentImg(urlAndFileArr) {
      const fileUrl = urlAndFileArr[0] // 文件URL
      const file = urlAndFileArr[1] // File对象
      console.log('删除内容图片', fileUrl, file)
      this.$deleteImg(fileUrl)
    },

  },
}
</script>

<style>
.article-edit-container {
  margin-bottom: 100px;
  box-shadow: 0 0 20px black;
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.9);
  padding: 30px 50px 30px 10px;
}

.avatar-uploader .el-upload {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}

.avatar-uploader .el-upload:hover {
  border-color: #409EFF;
}

.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 178px;
  line-height: 178px;
  text-align: center;
}

.avatar {
  width: 178px;
  height: 178px;
  display: block;
}
</style>
